package com.yvon.maple.service.msg.core.websocket.util;


import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Sets;
import com.yvon.maple.service.msg.core.websocket.attribute.Attributes;
import com.yvon.maple.service.msg.core.websocket.session.Session;
import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 会话跑龙套
 *
 * @author Yvon
 * @since 2022-11-07
 */
public class SessionUtil {
    /**
     * 用户名通道映射
     */
    private static final Map<String, Channel> usernameChannelMap = new ConcurrentHashMap<>();

    /**
     * 组id通道组地图
     */
    private static final Map<String, ChannelGroup> groupIdChannelGroupMap = new ConcurrentHashMap<>();

    /**
     * 订阅通道映射
     */
    private static final Map<String, Set<Channel>> subscribeChannelMap = new ConcurrentHashMap<>();

    /**
     * 绑定会话
     *
     * @param session 会话
     * @param channel 通道
     */
    public static void bindSession(Session session, Channel channel) {
        usernameChannelMap.put(session.getUsername(), channel);
        channel.attr(Attributes.SESSION).set(session);
    }

    /**
     * 联合国绑定会话
     *
     * @param channel 通道
     */
    public static void unBindSession(Channel channel) {
        if (hasLogin(channel)) {
            Session session = getSession(channel);
            usernameChannelMap.remove(session.getUsername());
            channel.attr(Attributes.SESSION).set(null);
            System.out.println(session + " 退出登录!");
        }
    }


    /**
     * 订阅
     *
     * @param type    类型
     * @param channel 通道
     */
    public static void subscribe(String type, Channel channel) {
        if (hasLogin(channel)) {
            Set<Channel> channels = subscribeChannelMap.get(type);
            if (CollUtil.isEmpty(channels)) {
                subscribeChannelMap.put(type, Sets.newHashSet(channel));
            }else {
                channels.add(channel);
                subscribeChannelMap.put(type, channels);
            }
        }
    }

    /**
     * 获得订阅列表
     *
     * @param type 类型
     * @return {@link Set}<{@link Channel}>
     */
    public static Set<Channel> getSubscribeList(String type) {
        return subscribeChannelMap.get(type);
    }

    /**
     * 取消订阅
     *
     * @param type    类型
     * @param channel 通道
     */
    public static void cancelSubscribe(String type, Channel channel) {
        Set<Channel> channels = subscribeChannelMap.get(type);
        if (CollUtil.isNotEmpty(channels)) {
            Set<Channel> set = channels.stream().filter(ch -> !channel.equals(ch)).collect(Collectors.toSet());
            subscribeChannelMap.put(type, set);
        }
    }

    /**
     * 已登录
     *
     * @param channel 通道
     * @return boolean
     */
    public static boolean hasLogin(Channel channel) {

        return getSession(channel) != null;
    }


    /**
     * 获得会话
     *
     * @param channel 通道
     * @return {@link Session}
     */
    public static Session getSession(Channel channel) {

        return channel.attr(Attributes.SESSION).get();
    }

    /**
     * 得到渠道
     *
     * @param username 用户名
     * @return {@link Channel}
     */
    public static Channel getChannel(String username) {

        return usernameChannelMap.get(username);
    }

    /**
     * 结合通道组
     *
     * @param groupId      组id
     * @param channelGroup 通道组
     */
    public static void bindChannelGroup(String groupId, ChannelGroup channelGroup) {
        groupIdChannelGroupMap.put(groupId, channelGroup);
    }

    /**
     * 得到通道组
     *
     * @param groupId 组id
     * @return {@link ChannelGroup}
     */
    public static ChannelGroup getChannelGroup(String groupId) {
        return groupIdChannelGroupMap.get(groupId);
    }


    /**
     * 得到oline通道
     *
     * @return {@link Collection}<{@link Channel}>
     */
    public static Collection<Channel> getOlineChannel() {
        return usernameChannelMap.values();
    }

}
